package game.leon.engine.gate.away;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.*;

/**
 * User: bianpeng
 * Date: 11-12-28
 * 上行消息, 不支持消息合并, 有一条发一条.
 * 下行需要支持消息合并
 */
public class GatewayCodecFactory implements ProtocolCodecFactory {
    static class GatewayProtocolDecoder extends CumulativeProtocolDecoder {
        private static final String DECODE_STATE = "DECODE_STATE";
        public static final int BUFFER_PREFIX_LENGTH = 6;
        @Override
        protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
            DecodeState state = (DecodeState) session.getAttribute(DECODE_STATE);
            if (state == null) {
                state = new DecodeState();
                session.setAttribute(DECODE_STATE, state);
            }
            if (state.step == 0) {
                if (in.remaining() > BUFFER_PREFIX_LENGTH) {
                    // 这里是实际数据长度, 8字节的PREFIX长度, 不包含在内
                    state.mid = in.getUnsignedShort();
                    state.vid = in.getUnsignedShort();
                    state.datasize = in.getUnsignedShort();
                    state.step = 1;
                }
            }
            if (state.step == 1 && in.remaining() >= state.datasize) {
                byte[] data = new byte[state.datasize];
                in.get(data);
                out.write(new GatewayRawData(state.mid, state.vid, data));
                state.step = 0;
                return true;
            }
            return false;
        }
    }
    private static class DecodeState {
        int step;
        // message body
        int mid;
        int vid;
        int datasize;
    }
    static class GatewayProtocolEncoder extends ProtocolEncoderAdapter {
        public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
            GatewayRawData raw = (GatewayRawData) message;
            assert raw != null;
            IoBuffer buffer = IoBuffer.allocate(raw.getData().length + GatewayProtocolDecoder.BUFFER_PREFIX_LENGTH, false);
            buffer.putUnsignedShort(raw.getMid());
            buffer.putUnsignedShort(raw.getVid());
            buffer.putUnsignedShort(raw.getData().length);
            buffer.put(raw.getData());
            buffer.flip();
            out.write(buffer);
        }
    }


    private ProtocolEncoder encoder;
    private ProtocolDecoder decoder;
    public GatewayCodecFactory() {
        decoder = new GatewayProtocolDecoder();
        encoder = new GatewayProtocolEncoder();
    }
    public ProtocolEncoder getEncoder(IoSession session) throws Exception {
        return encoder;
    }
    public ProtocolDecoder getDecoder(IoSession session) throws Exception {
        return decoder;
    }
}
